import os
import wx
import wx.lib.agw.aui as aui
from robot.parsing.model import TestCase
from robot.parsing.model import TestCaseFile, TestDataDirectory, TestCase
from rwb.widgets import TestSuiteTreeCtrl, FILTER_TAG, FILTER_NAME, FILTER_NONE, EVT_RSA
from rwb.widgets import RobotBrowserCtrl
import rwb
import firebrick

#import TestSuiteTreeCtrl
#from TestSuiteTreeCtrl import TestSuiteTreeCtrl

ID_FILTER_BY_NAME = wx.NewId()
ID_FILTER_BY_TESTCASE_TAGS = wx.NewId()
ID_FILTER_BY_ALL_TAGS = wx.NewId()

FID = "rwb.core.navigator"

class RobotFrameworkPlugin(firebrick.Plugin):
    '''A plugin that creates a hierarchical view of a test suite

    This view includes a checkbox next to each item so one could, for example,
    choose a subset of tests to run. 
    '''

    def __init__(self, app):
        super(RobotFrameworkPlugin,self).__init__(_id="rwb.core.robot",
                            url=None, version="0.1", 
                            name="Robot Framework Plugin",
                            default_settings = {})

    def enable(self):
        rwb.app.Register(SuiteNavigatorPanel)
        rwb.app.Register(SuiteBrowserPanel)
        self.active = True

    def disable(self):
        self.active = False
        rwb.app.Unregister(NavigationPanel)
        rwb.app.Unregister(SuiteBrowserPanel)

# FIXME
# I don't  like having all these panels in this one file
# but my plugin code doesn't let me break them apart.
class SuiteBrowserPanel(firebrick.BasePanel):
    '''This displays the suite that is selected in the navigator

    This window isn't designed for editing, it displays the
    test case in an easy-to-read format. Note that "selected"
    in this context means exactly that -- whatever is single-clicked
    on is what is displayed.
    '''

    name = "Robot Suite Browser"
    _id = "rwb.core.suite-browser"

    def __init__(self, parent):
        super(SuiteBrowserPanel, self).__init__(parent)
        self.window = parent
        self.browser = RobotBrowserCtrl(self, wx.ID_ANY)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.browser, 1, wx.EXPAND)
        self.SetSizer(sizer)
        parent.auimgr.AddPane(self, aui.AuiPaneInfo().Center().
                              CaptionVisible(True).
                              Caption("Robot Browser").
                              BestSize(wx.Size(300,600)).
                              Show(False).
                              Name(self._id))

        rwb.app.Subscribe("object_selected", self.OnObjectSelected)

    def OnObjectSelected(self, message):
        obj = message.data["object"]
        self.browser.Load(obj)

class SuiteNavigatorPanel(firebrick.BasePanel):
    name = "Robot Suite Navigator"
    _id = FID

    def __init__(self, parent):
        super(SuiteNavigatorPanel, self).__init__(parent)
        self.window = parent
        self._create_tree()
        self.root = self.tree.AddRoot("root")

        # list of nodes, to make it easier to iterate over all tests
        self._nodes = []
        parent.auimgr.AddPane(self, aui.AuiPaneInfo().Left().
                              CaptionVisible(True).
                              Caption("Test Suite Navigator").
                              BestSize(wx.Size(300,600)).
                              Show(False).
                              Name(FID))

        # default filter type
        self.filter_type = FILTER_NAME

#        rwb.app.Subscribe("suite.loaded", self.OnSuiteLoaded)
        rwb.app.Subscribe("end.suite", self.OnEndSuite)
        rwb.app.Subscribe("open", self.OnOpen)

    def OnOpen(self, message):
#        dialog = wx.Progress
        suite = message.data["suite"]
        if suite:
            # we only care about test suites
            self.tree.AddSuite(suite)
#        self.SetSuite(rwb.suite)

    def Reset(self):
        '''Reset the state of the navigator icons'''
        # obviously, this needs to be implemented :-(
        pass

    def SetState(self, longname, status):
        print "*** SetState: %s = %s" % (longname, status)
        self.tree.SetState(longname, status.lower())

    def SetSuite(self, suite):
        self.tree.SetSuite(suite)
        self.tree.Redraw()
        wx.CallAfter(self.tree.ExpandAllChildren, self.tree.GetRootItem())
    
    def OnEndSuite(self, message):
        print "Navigator.OnEndSuite:", message

    def GetCheckedTestsByName(self):
        result = []
        for item in self._nodes:
            if self.tree.IsItemChecked(item):
                obj = self.tree.GetItemPyData(item)
                result.append((self._get_longname(obj.parent), obj.name))
#                result.append(self._get_longname(obj))
        return result
    
    def _create_tree(self):
        self.tree = TestSuiteTreeCtrl(self)
        self.filter_menu = wx.Menu()
        # these need to be radio items rather than simple menu items
        item = self.filter_menu.Append(ID_FILTER_BY_NAME, 
                                       "Filter by name", kind=wx.ITEM_RADIO)
        item = self.filter_menu.Append(ID_FILTER_BY_TESTCASE_TAGS, 
                                       "Filter by testcase tags", kind=wx.ITEM_RADIO)
#        item = filter_menu.Append(ID_FILTER_BY_ALL_TAGS, "Filter by all tags")
        self.filter = wx.SearchCtrl(self, size=(200,-1), style=wx.TE_PROCESS_ENTER)
        self.filter.SetMenu(self.filter_menu)
        self.filter.SetDescriptiveText("filter by testcase name")
        self.filter.ShowCancelButton(True)
        self.filter.ShowSearchButton(True)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.tree, 1, wx.EXPAND)
        sizer.Add(self.filter, 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 2)
        self.SetSizerAndFit(sizer)
        self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnTreeSelection)
        self.tree.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnTreeItemActivated)
        self.tree.Bind(EVT_RSA, self.OnRSA)

        self.filter.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, self.OnCancelFilter)
        self.filter.Bind(wx.EVT_TEXT, self.OnFilter)
        self.filter.Bind(wx.EVT_TEXT_ENTER, self.OnFilter)
        self.filter.Bind(wx.EVT_MENU, self.OnFilterMenu)
        self.SetFilterType(ID_FILTER_BY_NAME)

    def OnRSA(self, event):
        panel = self.window.GetPanel("rsa.log")
        panel.Run(event.tcuk)

    def OnCancelFilter(self, event):
        self.filter.SetValue("")
        self.tree.Filter(FILTER_NONE)
        event.Skip()

    def OnFilterMenu(self, event):
        self.SetFilterType(event.GetId())
        event.Skip()

    def SetFilterType(self, filter_type):
        '''Filter_type must be one of the filter IDs (eg: ID_FILTER_BY_NAME)'''
        label = self.filter_menu.GetLabel(filter_type)
        self.filter.SetDescriptiveText(label)
        self.filter.SetToolTipString(label)
#        self.filter_menu.Check(filter_type, True)

        if filter_type == ID_FILTER_BY_NAME:
            self.filter_type = FILTER_NAME
        elif filter_type == ID_FILTER_BY_TESTCASE_TAGS:
            self.filter_type = FILTER_TAG
        elif filter_type == ID_FILTER_BY_ALL_TAGS:
            # this isn't (yet) supported
            self.filter.SetDescriptiveText("filter by all tags")
            self.filter_type = FILTER_TAG

    def OnFilter(self, event):
        self.tree.Filter(self.filter_type, self.filter.GetValue())
        event.Skip()

    def SelectByName(self, longname):
        self.tree.SelectNodeByName(longname)

    def OnTreeItemActivated(self, event):
        item = event.GetItem()
        rwb.log.debug("item activated: %s" % item)
        if item:
            node = self.tree.GetItemPyData(item)
#            test_panel = rwb.app.GetPanel(self.window, "rwb.core.test_window")
            # should this be "self.parent.Show(...)?"
#            test_panel.Show(node.tcuk)
            rwb.app.Publish("object_activated", object=node.tcuk)

        # if we call event.Skip() the item's children will be collapsed or
        # expanded, which I don't think we want (since double-click means
        # "load this in the editor"
#        event.Skip()

    def OnTreeSelection(self, event):
        item = event.GetItem()
        node = self.tree.GetItemPyData(item)
        rwb.app.Publish("object_selected", object=node.tcuk)
        event.Skip()

